package com.whq.thrift.api.common.httpsignature;

import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.whq.common.encrypt.md5.MD5Coder;
import com.whq.thrift.api.common.constants.CommonConfigConstants;

/**
 * 签名工具类
 * 
 * @author wanghuaiqiang
 * 
 */
public class SignatureUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(SignatureUtil.class);
	
	/**
	 * 获取签名信息
	 * @param businessParams
	 * @param merchantName
	 * @param secretKey
	 * @param signType
	 * @param timestampSecond
	 * @param merchantNameParamName
	 * @return
	 */
	public static String getSignature(Map<String, String> businessParams, String merchantName,
			String secretKey, String signType, String timestampSecond, String merchantNameParamName) {
		Map<String, String> signedParamsMap = generateSignatureParam(businessParams, merchantName, secretKey, signType, timestampSecond, merchantNameParamName);
		return signedParamsMap.get(CommonConfigConstants.API_PARAM_SIGNCODE);
	}
	
	/**
	 * 获取签名信息
	 * @param businessParams
	 * @param merchantName
	 * @param secretKey
	 * @param signType
	 * @param timestampSecond
	 * @param merchantNameParamName
	 * @return
	 */
	public static String getSignature(Map<String, String> businessParams, String merchantName,
			String secretKey, String signType, long timestampSecond, String merchantNameParamName) {
		Map<String, String> signedParamsMap = generateSignatureParam(businessParams, merchantName, secretKey, signType, timestampSecond, merchantNameParamName);
		return signedParamsMap.get(CommonConfigConstants.API_PARAM_SIGNCODE);
	}
	
	/**
	 * 参数签名
	 * @param businessParams
	 * @param secretKey
	 * @param signType
	 * @return
	 */
	public static Map<String, String> generateSignatureParam(Map<String, String> businessParams, String merchantName,
			String secretKey, String signType) {
		return generateSignatureParam(businessParams, merchantName, secretKey, signType, (System.currentTimeMillis() / 1000l), CommonConfigConstants.API_PARAM_MERCHANT_NAME);
	}
	
	/**
	 * 参数签名
	 * @param businessParams
	 * @param merchantName
	 * @param secretKey
	 * @param signType
	 * @param timestampSecond
	 * @param merchantNameParamName
	 * @return
	 */
	public static Map<String, String> generateSignatureParam(Map<String, String> businessParams, String merchantName,
			String secretKey, String signType, long timestampSecond, String merchantNameParamName) {
		return generateSignatureParam(businessParams, merchantName,
				secretKey, signType, "" + timestampSecond, merchantNameParamName);
	}
	
	/**
	 * 参数签名
	 * @param businessParams
	 * @param merchantName
	 * @param secretKey
	 * @param signType
	 * @param timestampSecond
	 * @param merchantNameParamName
	 * @return
	 */
	public static Map<String, String> generateSignatureParam(Map<String, String> businessParams, String merchantName,
			String secretKey, String signType, String timestampSecond, String merchantNameParamName) {
		TreeMap<String, String> signedParamsMap = new TreeMap<String, String>();
		if (businessParams != null) {
			signedParamsMap.putAll(businessParams);
		}

		signedParamsMap.put(CommonConfigConstants.API_PARAM_SIGN_TYPE, signType);
		signedParamsMap.put(merchantNameParamName, merchantName);
		signedParamsMap.put(CommonConfigConstants.API_PARAM_TIMESTAMP, "" + timestampSecond);

		StringBuffer verifyOrigSb = new StringBuffer("");

		for (Iterator<String> iterator = signedParamsMap.keySet().iterator(); iterator.hasNext();) {
			String paraName = (String) iterator.next();
			if (paraName == null) {
				continue;
			}

			String paraValue = signedParamsMap.get(paraName);

			if (!CommonConfigConstants.API_PARAM_SIGNCODE.equals(paraName)) {
				if (StringUtils.isNotEmpty(paraValue)) {
					verifyOrigSb.append(paraName + "=" + paraValue);
				} else {
					verifyOrigSb.append(paraName + "=");
				}
			}
		}
		verifyOrigSb.append(secretKey);
		
		LOGGER.debug("signature string: " + verifyOrigSb.toString());
		
		String realVerifyCode = "";
		if ("MD5".equals(signType)) {
			realVerifyCode = MD5Coder.md5Encode(verifyOrigSb.toString());
		}
		signedParamsMap.put(CommonConfigConstants.API_PARAM_SIGNCODE, realVerifyCode);

		return signedParamsMap;
	}

	/**
	 * 生成签名后的url
	 * @param urlPrefix
	 * @param businessParams
	 * @param secretKey
	 * @param signType
	 * @return
	 */
	public static String generateSignedUrl(String urlPrefix, Map<String, String> businessParams, String merchantName,
			String secretKey, String signType) {
		Map<String, String> paramsMap = generateSignatureParam(businessParams, merchantName, secretKey, signType);
		StringBuffer sbRet = new StringBuffer();
		if (urlPrefix == null) {
			urlPrefix = "";
		}
		boolean haveQuestionMark = false;
		if (urlPrefix.indexOf("?") >= 0) {
			haveQuestionMark = true;
		}
		sbRet.append(urlPrefix.trim());
		if ((paramsMap != null) && (!paramsMap.isEmpty())) {
			int paramCount = 0;
			for (Iterator<String> iterator = paramsMap.keySet().iterator(); iterator.hasNext();) {
				String paramKey = (String) iterator.next();
				if (StringUtils.isBlank(paramKey)) {
					continue;
				}
				String paramVal = paramsMap.get(paramKey);
				if (paramVal == null) {
					paramVal = "";
				}
				if ( (!haveQuestionMark) 
						&& (paramCount == 0)
						) {
					sbRet.append("?");
				} else {
					sbRet.append("&");
				}
				sbRet.append(paramKey.trim() + "=");
				if ( (StringUtils.isNotBlank(paramVal)) 
						&& (!"null".equals(paramVal))
						&& (!"NULL".equals(paramVal))
						){
					try {
						paramVal = URLEncoder.encode(paramVal, "UTF-8");
					} catch (Exception e) {
						LOGGER.error(" URLEncoder(" + paramVal + ") error: ", e);
					}

					sbRet.append(paramVal);
				}
				paramCount++;
			}
		}

		return sbRet.toString();
	}
}
